home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
inline.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
8KB
|
311 lines
/*
* @(#)inline.c 1.7 9/24/87
*/
#include "assert.h"
#include "error.h"
#include "ident.h"
#include "nodes.h"
#include "builtins.h"
#include "sequence.h"
#include "system.h"
#include "trace.h"
#include "opNames.h"
#include "option.h"
/*
* inline's job is to decide if operations are inline-able, and set their
* isInLineAble bit in the b.opdef. It also finds monitored operations
* where signals happen as the last thing and sets the useSignalAndExit bit
* in b.signalstat. It is also supposed to find objects that have monitors where
* the monitor can be elided.
*/
int countStatements(p)
NodePtr p;
{
register NodePtr q;
register int thisCount = 0;
if ((int) p <= 0x200) return(0);
switch (p->tag) {
case P_ASSIGNSTAT:
case P_ASSERTSTAT:
case P_FIXSTAT:
case P_REFIXSTAT:
case P_UNFIXSTAT:
case P_MOVESTAT:
case P_PRIMSTAT:
case P_WAITSTAT:
case P_SIGNALSTAT:
case P_VARDECL:
case P_CONSTDECL:
case P_EXITSTAT:
case P_CHECKPOINTSTAT:
case P_RETURNSTAT:
case P_RETURNANDFAILSTAT:
return(1);
case P_IFSTAT:
thisCount = 1;
break;
default:
break;
}
Sequence_For(q, p)
thisCount += countStatements(q);
Sequence_Next
return(thisCount);
}
int countNodes(p)
NodePtr p;
{
register NodePtr q;
register int thisCount = 1;
if ((int) p <= 0x200) return(0);
Sequence_For(q, p)
thisCount += countNodes(q);
Sequence_Next
return(thisCount);
}
#define INLINENODELIMIT 30
#define INLINESTATEMENTLIMIT 3
typedef struct sFSRec {
NodePtr signals;
Boolean isStatement;
} FSRec, *FSRecPtr;
FSRec findTerminalSignals(p)
NodePtr p;
{
register NodePtr q, r;
FSRec myResult, hisResult;
myResult.isStatement = FALSE;
myResult.signals = NULL;
if ((int) p <= 0x200) return(myResult);
switch (p->tag) {
case P_FAILUREHANDLER:
case P_UNAVAILABLEHANDLER:
break;
case P_BLOCK:
return(findTerminalSignals(p->b.block.stats));
case T_SEQUENCE:
Sequence_For(q, p)
hisResult = findTerminalSignals(q);
/* merge the results */
if (hisResult.isStatement) {
Free(myResult.signals);
myResult.signals = NN;
}
Sequence_For(r, hisResult.signals)
Sequence_Add(&myResult.signals, r);
Sequence_Next
Free(hisResult.signals);
Sequence_Next
break;
case P_IFSTAT:
myResult.isStatement = TRUE;
Sequence_For(q, p->b.ifstat.ifclauses)
hisResult = findTerminalSignals(q->b.ifclause.stats);
Sequence_For(r, hisResult.signals)
Sequence_Add(&myResult.signals, r);
Sequence_Next
Free(hisResult.signals);
Sequence_Next
if ((q = p->b.ifstat.elseclause) != NN) {
hisResult = findTerminalSignals(q->b.elseclause.stats);
Sequence_For(r, hisResult.signals)
Sequence_Add(&myResult.signals, r);
Sequence_Next
Free(hisResult.signals);
}
break;
case P_IFCLAUSE:
case P_ELSECLAUSE:
break;
case P_LOOPSTAT:
case P_ASSIGNSTAT:
case P_ASSERTSTAT:
case P_REFIXSTAT:
case P_FIXSTAT:
case P_UNFIXSTAT:
case P_MOVESTAT:
case P_PRIMSTAT:
case P_WAITSTAT:
case P_VARDECL:
case P_CONSTDECL:
case P_EXITSTAT:
case P_CHECKPOINTSTAT:
myResult.isStatement = TRUE;
break;
case P_RETURNSTAT:
case P_RETURNANDFAILSTAT:
myResult.isStatement = FALSE;
break;
case P_SIGNALSTAT:
myResult.isStatement = TRUE;
Sequence_Add(&myResult.signals, p);
break;
default:
break;
}
return (myResult);
}
static int compareImports(left, right)
NodePtr *left, *right;
{
NodePtr l, r;
l = (*left)->b.setq.outer;
r = (*right)->b.setq.outer;
if (l->tag != P_SYMREF) return(-1);
if (r->tag != P_SYMREF) return(1);
return(l->b.symref.symbol->itsSymbolNumber -
r->b.symref.symbol->itsSymbolNumber);
}
extern Boolean isARealImport();
static Boolean doImportsMatch(sig, obj)
register NodePtr sig, obj;
{
Symbol importedSym, aParam;
register NodePtr import;
register int nextParam = 0;
TRACE2(imports, 1, "Checking object %s against signature %s",
ATName(obj), SigName(sig));
Sequence_For(import, obj->b.oblit.setq)
if (isARealImport(import->b.setq.inner->b.symdef.symbol, FALSE)) {
if (import->b.setq.outer->tag != P_SYMREF) return(FALSE);
importedSym = import->b.setq.outer->b.symdef.symbol;
if (nextParam >= Sequence_Length(sig->b.opsig.params)) return(FALSE);
aParam = sig->b.opsig.params->b.children[nextParam]->b.param.sym->b.symdef.symbol;
TRACE2(imports, 1, "Symbol %s must match %s", STName(importedSym),
STName(aParam));
if (aParam == importedSym) {
nextParam ++;
TRACE0(imports, 1, "yes!");
} else {
TRACE0(imports, 1, "no!\nReturning FALSE");
return(FALSE);
}
}
Sequence_Next
TRACE0(imports, 1, "Returning TRUE");
return(TRUE);
}
extern void DisplayTree();
checkWonderfullyImmutable(p)
NodePtr p;
{
if (p->b.oblit.process != NN) {
ErrorMessage(p, "Immutable objects may not contain processes");
}
if (p->b.oblit.monitor != NN &&
!p->b.oblit.monitor->b.monitor.mayBeElided &&
Sequence_Length(p->b.oblit.monitor->b.monitor.decls) != 0 &&
Sequence_Length(p->b.oblit.monitor->b.monitor.ops) != 0) {
ErrorMessage(p, "Immutable objects may not contain monitors");
}
}
void detectInlines(p)
NodePtr p;
{
register NodePtr q;
FSRec andExitableSignals;
register Boolean isInlineable = TRUE;
Boolean done = FALSE;
if ((int) p <= 0x200) return;
switch (p->tag) {
case P_CONSTDECL:
if (p->b.constdecl.sym->b.symdef.symbol->isManifest) {
detectInlines(p->b.constdecl.sym->b.symdef.symbol->value.value);
done = TRUE;
}
break;
case P_INVOC:
default:
break;
}
if (!done) Sequence_For(q, p)
if ((int)q > 0x200) detectInlines(q);
Sequence_Next
switch (p->tag) {
case P_OBLIT:
if (! p->b.oblit.f.isTypeVariable &&
! p->b.oblit.f.dependsOnTypeVariable &&
! p->b.oblit.f.isManifest) {
if (Sequence_Length(p->b.oblit.setq) > 1) {
IFTRACE(imports, 1) {
trace(1, "Sorting imports of %s", ATName(p));
trace(1, "Before:");
DisplayTree(stdout, p->b.oblit.setq, 0, 999);
}
qsort((char *)&(p->b.oblit.setq->b.children[0]),
Sequence_Length(p->b.oblit.setq),
sizeof(NodePtr),
compareImports);
IFTRACE(imports, 1) {
trace(1, "After:");
DisplayTree(stdout, p->b.oblit.setq, 0, 999);
}
}
}
if (p->b.oblit.f.immutable) {
checkWonderfullyImmutable(p);
}
break;
case P_OPDEF:
#define PESSIMISTIC
#ifdef PESSIMISTIC
q = p->b.opdef.body;
if (q->b.block.failurehandler != NN) isInlineable = FALSE;
else if (q->b.block.unavailablehandler != NN) isInlineable = FALSE;
else {
q = q->b.block.stats;
if (Sequence_Length(q) != 1) isInlineable = FALSE;
else if (q->b.children[0]->tag == P_PRIMSTAT) isInlineable = TRUE;
else if (q->b.children[0]->tag == P_ASSIGNSTAT) {
q = q->b.children[0];
if (Sequence_Length(p->b.opdef.sig->b.opsig.results) != 1) isInlineable = FALSE;
else if (q->b.assignstat.right->nChildren != 1) isInlineable = FALSE;
else if (q->b.assignstat.left->nChildren != 1) isInlineable = FALSE;
else if (q->b.assignstat.right->b.children[0]->tag == P_OBLIT) {
isInlineable = doImportsMatch(p->b.opdef.sig,
q->b.assignstat.right->b.children[0]);
} else IFOPTION(inline, 1) {
isInlineable = TRUE;
} else {
isInlineable = FALSE;
}
} else {
isInlineable = FALSE;
}
}
p->b.opdef.isInlineable = isInlineable;
#else
if (countNodes(p) <= INLINENODELIMIT && countStatements(p) <= INLINESTATEMENTLIMIT) {
p->b.opdef.isInlineable = TRUE;
}
#endif
andExitableSignals = findTerminalSignals(p->b.opdef.body);
Sequence_For(q, andExitableSignals.signals)
assert(q->tag == P_SIGNALSTAT);
q->b.signalstat.useSignalAndExit = TRUE;
Sequence_Next
Free(andExitableSignals.signals);
break;
default:
break;
}
}